<template>
  <div class="ifc-canvas" ref="canvasContainer">
    <el-loading 
      v-loading="loading" 
      :text="loadingText"
      :element-loading-background="'rgba(0, 0, 0, 0.7)'"
    />
    <div v-if="error" class="error-message">
      <el-alert
        :title="error"
        type="error"
        :closable="true"
        show-icon
        @close="error = null"
      />
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { useIfcStore } from '@/store'
import { IfcService } from '@/services/ifcService.js'

const props = defineProps({
  modelUrl: {
    type: String,
    default: null
  }
})

const emit = defineEmits(['viewerReady', 'modelLoaded'])

const canvasContainer = ref(null)
const loading = ref(false)
const loadingText = ref('加载 IFC 模型中...')
const error = ref(null)
const viewer = ref(null)
const service = ref(null)
const store = useIfcStore()

onMounted(async () => {
  if (!canvasContainer.value) return
  
  try {
    loading.value = true
    error.value = null
    
    const { IfcViewerAPI } = await import('web-ifc-viewer')
    const ifcViewer = new IfcViewerAPI({
      container: canvasContainer.value,
      backgroundColor: { r: 0.04, g: 0.05, b: 0.07 }
    })
    
    // 详细诊断：检查 viewer 的结构
    console.log('=== IFC Viewer 诊断信息 ===')
    console.log('IfcViewerAPI 实例:', ifcViewer)
    console.log('Viewer 类型:', typeof ifcViewer)
    console.log('Viewer 的键:', Object.keys(ifcViewer))
    console.log('IFC 属性:', ifcViewer.IFC)
    console.log('IFC 类型:', typeof ifcViewer.IFC)
    
    // 检查多个可能的访问路径
    const possiblePaths = [
      'IFC',
      'ifc',
      'IfcManager',
      'ifcManager',
      'context',
      'manager'
    ]
    
    console.log('检查可能的 IFC 管理器路径:')
    for (const path of possiblePaths) {
      const value = ifcViewer[path]
      console.log(`  ${path}:`, value ? '存在' : '不存在', value ? `(${typeof value})` : '')
      if (value && typeof value === 'object') {
        console.log(`    ${path} 的键:`, Object.keys(value).slice(0, 10))
      }
    }
    
    // 等待 IFC 管理器出现（同步等待，不设置超时）
    console.log('等待 IFC 管理器初始化...')
    
    let ifcManager = null
    let waitCount = 0
    while (!ifcManager) {
      // 尝试多个可能的访问方式
      ifcManager = ifcViewer.IFC || 
                   ifcViewer.ifc ||
                   ifcViewer.context?.ifc ||
                   ifcViewer.IfcManager
      
      if (!ifcManager) {
        waitCount++
        await new Promise(resolve => setTimeout(resolve, 50))
        
        // 每 20 次检查输出一次诊断信息（约 1 秒）
        if (waitCount % 20 === 0) {
          console.log(`等待中... (${waitCount * 50}ms)`)
          console.log('当前 viewer.IFC:', ifcViewer.IFC)
          console.log('当前 viewer 的键:', Object.keys(ifcViewer).filter(k => k.toLowerCase().includes('ifc')))
        }
      }
    }
    
    console.log('✓ IFC 管理器已找到')
    console.log('IFC 管理器类型:', typeof ifcManager)
    console.log('IFC 管理器的键:', Object.keys(ifcManager))
    
    console.log('✓ IFC 管理器已找到，准备设置 WASM 路径...')
    
    // 关键修复：正确处理 WASM 路径，避免版本不匹配问题
    // web-ifc-viewer 1.0.218 需要与 web-ifc 版本匹配
    try {
      if (ifcManager.setWasmPath) {
        // 方法 1：不设置路径，让 web-ifc-viewer 使用默认路径（如果支持）
        // 方法 2：使用与安装版本匹配的 WASM 路径
        // 方法 3：从 node_modules 复制 WASM 文件到 public 目录（推荐）
        
        // 首先检查是否可以不设置（某些版本会自动处理）
        console.log('检查 IFC 管理器是否需要设置 WASM 路径...')
        
        // 如果方法已经可用，可能不需要设置 WASM 路径
        if (ifcManager.loadIfcFile && typeof ifcManager.loadIfcFile === 'function') {
          console.log('✓ loadIfcFile 方法已可用，可能不需要设置 WASM 路径')
        } else {
          // 需要设置 WASM 路径，优先使用本地文件
          console.log('需要设置 WASM 路径...')
          
          // 关键：使用与 web-ifc-viewer 1.0.218 匹配的 web-ifc 版本（0.0.39）
          // 尝试路径列表（按优先级）
          const wasmPaths = [
            '/node_modules/web-ifc/',           // Vite 开发服务器（使用本地安装的版本）
            './node_modules/web-ifc/',
            '/web-ifc/',                        // public 目录（如果已复制）
            // 使用与 web-ifc-viewer 1.0.218 匹配的版本 0.0.39，不是 0.0.53
            'https://unpkg.com/web-ifc@0.0.39/',
            'https://cdn.jsdelivr.net/npm/web-ifc@0.0.39/'
          ]
          
          let success = false
          for (const path of wasmPaths) {
            try {
              console.log(`尝试 WASM 路径: ${path}`)
              ifcManager.setWasmPath(path)
              console.log(`✓ WASM 路径设置成功: ${path}`)
              success = true
              break
            } catch (pathErr) {
              console.warn(`路径 ${path} 失败:`, pathErr.message || pathErr)
            }
          }
          
          if (!success) {
            console.warn('所有 WASM 路径都失败，但继续尝试（某些版本可能已内置）')
          }
        }
      } else {
        console.log('IFC 管理器没有 setWasmPath 方法，可能已内置 WASM 或不需要设置')
      }
    } catch (wasmErr) {
      console.warn('WASM 路径设置过程出错:', wasmErr)
      // 不抛出错误，某些版本可能不需要设置
      console.log('继续执行，某些版本的 web-ifc-viewer 可能已内置 WASM')
    }
    
    // 等待 loadIfcFile 方法就绪（同步等待，不设置超时）
    console.log('检查 loadIfcFile 方法...')
    console.log('IFC 管理器的所有方法:', Object.keys(ifcManager).filter(k => typeof ifcManager[k] === 'function'))
    
    let methodReady = false
    let methodWaitCount = 0
    while (!methodReady) {
      // 检查多个可能的方法名
      const method = ifcManager.loadIfcFile || 
                    ifcManager.loadIfc ||
                    ifcManager.load ||
                    ifcManager.loadFile
      
      if (method && typeof method === 'function') {
        methodReady = true
        console.log('✓ loadIfcFile 方法已就绪')
        // 如果方法名不同，保存正确的引用
        if (!ifcManager.loadIfcFile) {
          ifcManager.loadIfcFile = method
        }
      } else {
        methodWaitCount++
        await new Promise(resolve => setTimeout(resolve, 50))
        
        // 每 20 次检查输出一次诊断信息
        if (methodWaitCount % 20 === 0) {
          console.log(`等待 loadIfcFile 方法... (${methodWaitCount * 50}ms)`)
          console.log('当前方法检查:', {
            loadIfcFile: !!ifcManager.loadIfcFile,
            loadIfc: !!ifcManager.loadIfc,
            load: !!ifcManager.load,
            loadFile: !!ifcManager.loadFile
          })
        }
      }
    }
    
    console.log('✓ IFC 管理器初始化完成')
    console.log('可用的方法:', Object.keys(ifcManager).filter(k => typeof ifcManager[k] === 'function'))
    
    ifcViewer.axes.setAxes()
    ifcViewer.grid.setGrid()
    
    viewer.value = ifcViewer
    service.value = new IfcService(ifcViewer)
    
    emit('viewerReady', ifcViewer, service.value)
    
    // 添加点击事件
    canvasContainer.value.addEventListener('dblclick', onDoubleClick)
    
    // 添加鼠标移动事件（用于边框高亮）
    canvasContainer.value.addEventListener('mousemove', onMouseMove)
    canvasContainer.value.addEventListener('mouseleave', onMouseLeave)
    
    // 如果传入了模型 URL，自动加载
    if (props.modelUrl) {
      await loadModel(props.modelUrl)
    }
  } catch (err) {
    const errMsg = err.message || err.toString() || 'IFC viewer 初始化失败'
    error.value = errMsg
    store.setError(errMsg)
    console.error('IFC viewer 初始化错误:', err)
  } finally {
    loading.value = false
  }
})

onBeforeUnmount(() => {
  if (canvasContainer.value) {
    canvasContainer.value.removeEventListener('dblclick', onDoubleClick)
    canvasContainer.value.removeEventListener('mousemove', onMouseMove)
    canvasContainer.value.removeEventListener('mouseleave', onMouseLeave)
  }
  if (service.value) {
    service.value.clearHighlightEdges()
  }
  if (viewer.value) {
    viewer.value.dispose()
  }
})

watch(() => props.modelUrl, async (newUrl) => {
  if (newUrl && service.value) {
    await loadModel(newUrl)
  }
})

async function loadModel(url) {
  if (!service.value) {
    error.value = 'IFC 服务未初始化'
    return
  }
  
  try {
    loading.value = true
    error.value = null
    store.setLoading(true)
    
    // 先清除旧模型
    console.log('清除旧模型...')
    loadingText.value = '正在清除旧模型...'
    service.value.clearModel()
    
    // 等待清除完成
    await new Promise(resolve => setTimeout(resolve, 300))
    
    console.log('开始加载模型，URL:', url)
    
    if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//')) {
      // 远程 URL，使用 loadIfcUrl（内部会处理 CORS 问题）
      loadingText.value = '正在从服务器下载 IFC 文件...'
      await service.value.loadIfcUrl(url)
    } else {
      // 本地文件路径
      console.log('加载本地文件:', url)
      loadingText.value = '正在读取本地文件...'
      const response = await fetch(url)
      
      if (!response.ok) {
        throw new Error(`无法访问文件: HTTP ${response.status}`)
      }
      
      loadingText.value = '正在解析 IFC 文件...'
      const blob = await response.blob()
      if (blob.size === 0) {
        throw new Error('文件为空')
      }
      
      const fileName = url.split('/').pop() || 'model.ifc'
      const file = new File([blob], fileName, { 
        type: blob.type || 'application/octet-stream' 
      })
      
      loadingText.value = '正在加载 IFC 模型...'
      await service.value.loadIfcFile(file)
    }
    
    console.log('模型加载成功')
    loadingText.value = '加载 IFC 模型中...'
    emit('modelLoaded')
    store.setLoading(false)
  } catch (err) {
    const errMsg = err.message || err.toString() || '模型加载失败'
    error.value = errMsg
    store.setError(errMsg)
    loadingText.value = '加载 IFC 模型中...'
    console.error('loadModel 错误:', err)
  } finally {
    loading.value = false
    store.setLoading(false)
  }
}

async function onDoubleClick(event) {
  if (!service.value) return
  
  const picked = await service.value.pick(event)
  if (picked) {
    store.setSelectedElement(picked)
  } else {
    store.setSelectedElement(null)
  }
}

// 鼠标移动事件（边框高亮）- 性能优化版本
let hoverThrottleTimer = null
let lastHoverTime = 0
let lastPickedId = null // 缓存上次拾取的 ID，避免重复高亮
let rafId = null // requestAnimationFrame ID

function onMouseMove(event) {
  if (!service.value) {
    service.value?.clearHighlightEdges()
    return
  }
  
  // 如果高亮功能未启用，不监听拾取元素（优化效率）
  if (!service.value.isHighlightEnabled()) {
    return
  }
  
  // 节流：每200ms最多更新一次（减少频率）
  const currentTime = Date.now()
  if (currentTime - lastHoverTime < 200) {
    return
  }
  lastHoverTime = currentTime
  
  // 清除之前的定时器
  if (hoverThrottleTimer) {
    clearTimeout(hoverThrottleTimer)
  }
  
  // 使用 requestAnimationFrame 优化，避免阻塞渲染
  if (rafId) {
    cancelAnimationFrame(rafId)
  }
  
  rafId = requestAnimationFrame(() => {
    hoverThrottleTimer = setTimeout(async () => {
      try {
        // 使用 pick 方法拾取组件（异步方法）
        const picked = await service.value?.pick(event)
        
        if (picked && picked.expressID) {
          // 如果拾取的是同一个对象，跳过（避免重复高亮）
          if (lastPickedId === picked.expressID) {
            return
          }
          lastPickedId = picked.expressID
          
          // 高亮边框（金黄色）- 不需要相机
          service.value.highlightEdges([picked.expressID])
        } else {
          // 没有拾取到对象，清除高亮
          if (lastPickedId !== null) {
            lastPickedId = null
            service.value?.clearHighlightEdges()
          }
        }
      } catch (err) {
        console.error('鼠标悬停高亮错误:', err)
        service.value?.clearHighlightEdges()
        lastPickedId = null
      }
    }, 100) // 增加延迟到100ms
  })
}

// 鼠标离开画布时清除高亮
function onMouseLeave() {
  if (service.value) {
    service.value.clearHighlightEdges()
  }
  if (hoverThrottleTimer) {
    clearTimeout(hoverThrottleTimer)
    hoverThrottleTimer = null
  }
  if (rafId) {
    cancelAnimationFrame(rafId)
    rafId = null
  }
  lastPickedId = null
}

defineExpose({
  clearModel: () => {
    if (service.value) {
      service.value.clearModel()
    }
  },
  setHighlightEnabled: (enabled) => {
    if (service.value) {
      service.value.setHighlightEnabled(enabled)
    }
  },
  isHighlightEnabled: () => {
    if (service.value) {
      return service.value.isHighlightEnabled()
    }
    return false
  },
  loadFile: async (file) => {
    if (!service.value) {
      error.value = 'IFC 服务未初始化'
      return
    }
    try {
      loading.value = true
      error.value = null
      store.setLoading(true)
      
      // 加载前清除旧模型
      loadingText.value = '正在清除旧模型...'
      service.value.clearModel()
      
      // 等待清除完成
      await new Promise(resolve => setTimeout(resolve, 300))
      
      loadingText.value = '正在加载新模型...'
      await service.value.loadIfcFile(file)
      
      emit('modelLoaded')
      store.setLoading(false)
    } catch (err) {
      const errMsg = err.message || err.toString() || '模型加载失败'
      error.value = errMsg
      store.setError(errMsg)
      console.error('IFC 文件加载错误:', err)
      throw err
    } finally {
      loading.value = false
      store.setLoading(false)
      loadingText.value = '加载 IFC 模型中...'
    }
  },
  loadUrl: async (url) => {
    await loadModel(url)
  },
  getService: () => service.value,
  getViewer: () => viewer.value
})
</script>

<style scoped>
.ifc-canvas {
  width: 100%;
  height: 100%;
  position: relative;
  background: #0a0c12;
}

.error-message {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  min-width: 400px;
}
</style>

